/**
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// uint64_t EcmaResolveSecondArgument(uint64_t function_tagged_value);
.extern EcmaResolveSecondArgument

// handle ecma.callirangedyn
// regs set as follow
// x9 - frame.vregs, x10 - insn_ptr, x12 - method, x15 - acc, x13, x14 - temp

    // w15 <- num_args
    ldrh w15, [x10, 0]
    add w15, w15, 3 // func + new.target + resolved this

    // x9 <- range in frame.vregs
    ldrb w13, [x10, 2]
    add x9, x9, x13, lsl 3

    // x13 <- func (range0)
    ldr x13, [x9, 0 * FRAME_VREGISTER_SIZE]

    // x14 <- resolved this
    ldr w14, [x13, JSFUNCTION_FUNCTION_INFO_FLAG_OFFSET]
    tbz w14, JSFUNCTION_FUNCTION_INFO_FLAG_IS_STRICT_START_BIT, 3f
    mov w14, TAGGED_VALUE_UNDEFINED
1:

    // ABI arg reg 0 <- ark::Method*
    // ABI arg reg 1 <- num_args
    // x14           <- resolved this
    mov x0, x12
    mov w1, w15

    // Reserve stack args
    // x12 <- stack pointer
    sub x12, sp, x15, lsl 3
    and x12, x12, -16
    mov sp, x12

    // stack arg0 <- func (v0)
    // stack arg1 <- new_target (undefined)
    // stack arg2 <- resolved this
    str x13, [x12, 0 * 8]
    mov x13, TAGGED_VALUE_UNDEFINED
    str x13, [x12, 1 * 8]
    str x14, [x12, 2 * 8]

    // There's at least 4 function arguments
    // stack arg[3:6] <- range[1:4]
    ldr x13, [x9,  1 * FRAME_VREGISTER_SIZE]
    str x13, [x12, 3 * 8]
    ldr x13, [x9,  2 * FRAME_VREGISTER_SIZE]
    str x13, [x12, 4 * 8]
    ldr x13, [x9,  3 * FRAME_VREGISTER_SIZE]
    str x13, [x12, 5 * 8]
    ldr x13, [x9,  4 * FRAME_VREGISTER_SIZE]
    str x13, [x12, 6 * 8]

    subs w15, w15, 7
    beq .Linvoke

    add x9, x9, 4 * FRAME_VREGISTER_SIZE
    add x12, x12, 6 * 8
    lsl w15, w15, 3
2:
    ldr x13, [x9, x15]
    str x13, [x12, x15]
    subs w15, w15, FRAME_VREGISTER_SIZE
    bhi 2b

    b .Linvoke

3:
    // !IsStrict slowpath
    stp x9, x10,  [sp, #-16]!
    stp x12, x13, [sp, #-16]!
    stp x14, x15, [sp, #-16]!
    mov x0, x13
    bl EcmaResolveSecondArgument
    ldp x14, x15, [sp], #16
    ldp x12, x13, [sp], #16
    ldp x9, x10,  [sp], #16
    mov x14, x0
    b 1b
